今天早上看到公众号推送了阮一峰老师的文章JavaScript 的 this 原理,文章不是很长于是研究了一下。
看完自己的总结如下:
this
- this 指向函数运行时所在的环境。
- 函数运行在对象内,this 就指向该对象
- 运行在全局环境,this 就指向全局环境
- js 允许函数体内部引用当前环境外的其他变量,由于函数可以在不同运行环境执行,“当前环境外的其他变量”就是指“不同运行环境中的变量” ,那么这个时候就需要有一种机制,能够在函数体内部获得当前的运行环境,所以 ==
this
== 就应运而生了。
看到 ==js 允许函数体内部引用当前环境外的其他变量== 想到之前自己总结过的关于作用域的知识点:
作用域
- 函数定义的时候就被确定了作用域,与它在什么地方被调用执行无关
- 当前作用域没有定义的变量,即自由变量,会到父级作用域中查找,和执行作用域无关;
令我产生困惑的两句话:
- 函数定义的时候就被确定了作用域,和执行作用域无关
- js 允许函数体内部引用当前环境外的其他变量
这里的 ==执行作用域
== 与下文的 ==当前环境外的其他变量
== 如何理解或者做区分?
翻阅红宝书(第三版)p73,执行环境是 js 中最为重要的一个概念,总结如下:
- 函数的运行环境即其执行环境
- 每个函数都有自己的执行环境,执行环境定义了函数有权访问的其他数据,保存在变量对象之中。
- 当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链决定了访问变量对象的顺序。
- this 可以指向不同的运行环境,这里的运行环境本质上指的是对象,可以是内建对象、自定义对象或者全局对象。
- 函数定义时就被确定了作用域,这个作用域决定了其访问变量对象的顺序。而函数可以在不同环境被执行,这里的 ==不同环境== (可能是外层函数或者全局环境下)的作用域才是执行作用域。
- 所以
执行作用域
可以理解为 函数执行位置外部函数或者全局环境的作用域, 与函数自己的作用域(声明时就被确定了) 完全是两码事 - 当前环境外的其他变量即函数自己作用域外的其他变量
- 函数要想引用 当前环境外的其他变量 只能用 this ,this 指向当前运行环境,运行在对象内就指向对象,运行在全局环境就指向全局对象
- 咦,我自己怎么也有点乱。。
运行在全局环境的 this
众所周知,浏览器环境下 全局环境下的 this 就是 window,没有一点问题
// 浏览器环境下
var a = 'a'
this.b = 'b'
console.log(this.a) // a
console.log(b) // b
console.log(this===window) // true
但是...
// node 环境下
var x = 'xx'
global.y = 'yy'
// node 环境下输出
console.log(y); // yy global 属性挂载到了全局环境,
console.log(global.x) // undefined 全局环境中定义的x 变量并没有挂载到顶层对象global对象中
console.log(this === global) // false
console.log(JSON.stringify(this))// {} 空对象,并不是 global
查阅MDN发现:
// node 环境下
function f1() {
return this
}
console.log(f1() === global) // true
console.log(this === global) // false
node 环境下只有定义在函数内部的 this 才指向 global ?
那么, node 环境下 this 到底指向什么?经过和导师的沟通
终于发现
// node 环境下
this.num = '10'
global.test = '12'
console.log(module.exports) // {num: "10"}
console.log(this===module.exports) // true
那么 node 环境下 this 为什么指向 module.exports
这和模块化的设计又有什么关系?
发人深思...
天色已晚,且听下回分解。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。